package com.yuanrui.auth.domain.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.google.gson.Gson;
import com.yuanrui.auth.basic.entity.*;
import com.yuanrui.auth.basic.service.*;
import com.yuanrui.auth.common.enums.AuthUserStatusEnum;
import com.yuanrui.auth.common.enums.IsDeletedFlagEnum;
import com.yuanrui.auth.domain.constant.AuthConstant;
import com.yuanrui.auth.domain.convert.AuthUserConverter;
import com.yuanrui.auth.domain.entity.AuthPermissionBO;
import com.yuanrui.auth.domain.entity.AuthUserBO;
import com.yuanrui.auth.domain.redis.RedisUtil;
import com.yuanrui.auth.domain.service.AuthUserDomainService;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AuthUserDomainServiceImpl implements AuthUserDomainService {
    @Resource
    private AuthUserService authUserService;

    @Resource
    private AuthUserRoleService authUserRoleService;

    @Resource
    private AuthRoleService authRoleService;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private AuthPermissionService authPermissionService;

    @Resource
    private AuthRolePermissionService authRolePermissionService;

    private final String authPermissionPrefix = "auth:permission";

    private final String authRolePrefix = "auth:role";

    private final String salt = "yuanrui";

    private static final String LOGIN_PREFIX = "loginCode";

    @Override
    @Transactional
    @SneakyThrows
    public Boolean addUser(AuthUserBO authUserBO) {
        AuthUser exitUser = new AuthUser();
        exitUser.setUserName(authUserBO.getUserName());
        //校验用户是否存在
        List<AuthUser> exit=authUserService.queryByConditionCount(exitUser);
        if (!exit.isEmpty()){
            return true;
        }
        AuthUser authUser = AuthUserConverter.INSTANCE.convertToEntity(authUserBO);

        if (StringUtils.isNotBlank(authUser.getPassword())) {
            authUser.setPassword(SaSecureUtil.md5BySalt(authUser.getPassword(), salt));
        }
        authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        int insert = authUserService.insert(authUser);
        //建立用户与角色的关联
        AuthRole authRole = new AuthRole();
        authRole.setRoleKey(AuthConstant.NORMAL_USER);
        AuthRole result = authRoleService.queryByCondition(authRole);
        Long roleId = result.getId();
        Long userId = authUser.getId();
        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setUserId(userId);
        authUserRole.setRoleId(roleId);
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUserRoleService.insert(authUserRole);
        //将用户的角色信息存入缓存
        String roleKey = redisUtil.buildKey(authRolePrefix, authUser.getUserName());
        List<AuthRole> authRoles = new LinkedList<>();
        authRoles.add(result);
        redisUtil.set(roleKey, new Gson().toJson(authRoles));

        //将用户的权限信息存入缓存
        AuthRolePermission authRolePermission = new AuthRolePermission();
        authRolePermission.setRoleId(roleId);
        authRolePermission.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        List<AuthRolePermission> authRolePermissions = authRolePermissionService.queryByCondition(authRolePermission);
        //获取权限信息
        List<Long> permissionIds = authRolePermissions.stream().map(AuthRolePermission::getPermissionId).toList();
        List<AuthPermission> authPermissions = authPermissionService.queryByIds(permissionIds);
        String permissionKey = redisUtil.buildKey(authPermissionPrefix, authUser.getUserName());
        redisUtil.set(permissionKey, new Gson().toJson(authPermissions));
        return insert > 0;
    }

    /**
     * 修改用户信息
     *
     * @param authUserBO 用户信息
     * @return 修改结果
     */
    @Override
    public Boolean update(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserConverter.INSTANCE.convertToEntity(authUserBO);
        int update = authUserService.update(authUser);
        //有任何更新都要与缓存同步
        return update > 0;
    }

    @Override
    public Boolean delete(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        authUser.setId(authUserBO.getId());
        int update = authUserService.update(authUser);
        return update > 0;
    }

    @Override
    public SaTokenInfo doLogin(String validCode) {
        String verifyCodeKey = redisUtil.buildKey(LOGIN_PREFIX, validCode);
        String userOpenId= redisUtil.get(verifyCodeKey);
        if (StringUtils.isBlank(userOpenId)){
            return null;
        }
        AuthUserBO authUserBO = new AuthUserBO();
        authUserBO.setUserName(userOpenId);
        this.addUser(authUserBO);

        StpUtil.login(userOpenId);
        return StpUtil.getTokenInfo();
    }

    /**
     * 根据用户信息获取用户信息
     * @param authUserBO 用户信息
     * @return 用户信息
     */
    @Override
    public AuthUserBO getUserInfo(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setUserName(authUserBO.getUserName());
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        AuthUser authUserInfo = authUserService.queryUserInfo(authUser);
        return AuthUserConverter.INSTANCE.convertToBO(authUserInfo);
    }

    @Override
    public List<AuthUserBO> listUserInfoByIds(List<String> userNameList) {
        List<AuthUser> authUsers = authUserService.queryByUserNames(userNameList);
        return AuthUserConverter.INSTANCE.convertToEntity(authUsers);
    }
}
